import { any } from "../../core/logic";
import { Component, ComponentType } from "../Component";
import { Engine } from "../../Engine";
import { Texture } from "../../gpu/types/Texture";
import { Sampler } from "../../gpu/types/Sampler";
import { Buffer } from "../../gpu/types/Buffer";
/**
 * 基于IBL的环境光照。
 * @class
 * @extends {w.component.Component}
 * @memberof w.light
 */
class EnviromentLight extends Component {
  /**
   * @constructor
   * @param {*} opts 
   * @param {*} share 
   */
  constructor(opts = {}, share) {
    opts.type = any(opts.type, ComponentType.EnviromentLight);
    super(opts, share);
    this.irradianceMap = opts.value.irradianceMap
    this.prefilterMap = opts.value.prefilterMap
    this.brdfLUT = opts.value.brdfLUT
    this.addParam("iBLSampler");
    this.addParam("environmenIntensity");
  }
  get irradianceMap () {
    return this._irradianceMap
  }
  set irradianceMap (v) {
    this._irradianceMap = v
    this.addParam("irradianceMap");
  }
  get prefilterMap () {
    return this._prefilterMap
  }
  set prefilterMap (v) {
    this._prefilterMap = v
    this.addParam("prefilterMap");
  }
  get brdfLUT () {
    return this._brdfLUT
  }
  set brdfLUT (v) {
    this._brdfLUT = v
    this.addParam("brdfLUT");
  }
  toGPU () {
    //sampler
    let samplerData = {
      addressModeU: "repeat",
      addressModeV: "repeat",
      addressModeW: "repeat",
      magFilter: "linear",
      minFilter: "linear",
      mipmapFilter: "linear"
    }
    const engine = Engine.instance
    
    if (this.has("irradianceMap")) {
      let irradianceMapParameter = this.getParam('irradianceMap');
      if (!irradianceMapParameter) {
        irradianceMapParameter = new Texture({
          id: "irradianceMap",
          name: "irradianceMap",
          usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
          visibility: GPUShaderStage.FRAGMENT,
          sampleType: "float",
          format: engine.format,
          dimension: "cube",
          multisampled: false,
          data: this.irradianceMap
        })
        this.addParam('irradianceMap',irradianceMapParameter);
      } else {
        if(!irradianceMapParameter.state) {
          irradianceMapParameter.buffer(this.irradianceMap);
        }
      }
      irradianceMapParameter.state = true;
    }
    
    if (this.has("prefilterMap")) {
      let prefilterMapParameter = this.getParam('prefilterMap');
      if (!prefilterMapParameter) {
        prefilterMapParameter = new Texture({
          id: "prefilterMap",
          name: "prefilterMap",
          usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
          visibility: GPUShaderStage.FRAGMENT,
          sampleType: "float",
          format: engine.format,
          dimension: "cube",
          multisampled: false,
          data: this.prefilterMap
        })
        this.addParam('prefilterMap',prefilterMapParameter);
      } else {
        if(!prefilterMapParameter.state) {
          prefilterMapParameter.buffer(this.prefilterMap);
        }
      }
      prefilterMapParameter.state = true;
    }
    
    if (this.has("brdfLUT")) {
      let brdfLUTParameter = this.getParam('brdfLUT');
      if (!brdfLUTParameter) {
        brdfLUTParameter = new Texture({
          id: "brdfLUT",
          name: "brdfLUT",
          usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
          visibility: GPUShaderStage.FRAGMENT,
          sampleType: "float",
          format: engine.format,
          dimension: "2d",
          multisampled: false,
          data: this.brdfLUT
        })
        this.addParam('brdfLUT',brdfLUTParameter);
      } else {
        if(!brdfLUTParameter.state) {
          brdfLUTParameter.buffer(this.brdfLUT);
        }
      }
      brdfLUTParameter.state = true;
    }
    if (this.has("environmenIntensity")) {
      let environmenIntensityParameter = this.getParam('environmenIntensity');
      if (!environmenIntensityParameter) {
        environmenIntensityParameter = new Buffer({
          name: "environmenIntensity",
          usage:GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
          visibility:GPUShaderStage.FRAGMENT,
          type:"uniform",
          size:4,
          data:new Float32Array([Engine.instance.intensity])
      })
        this.addParam('environmenIntensity',environmenIntensityParameter);
      } else {
        if(!environmenIntensityParameter.state) {
          environmenIntensityParameter.buffer(new Float32Array([Engine.instance.intensity]));
        }
      }
      environmenIntensityParameter.state = true;
    }
    if (this.has("iBLSampler")) {
      let IBLSamplerParameter = this.getParam('iBLSampler');
      if (!IBLSamplerParameter) {
        IBLSamplerParameter = new Sampler({
          id: "iBLSampler",
          name: "iBLSampler",
          visibility: GPUShaderStage.FRAGMENT,
          type: "filtering",
          data: samplerData
        })
        this.addParam('iBLSampler',IBLSamplerParameter);
      } else {
        if(!IBLSamplerParameter.state) {
          IBLSamplerParameter.buffer(samplerData);
        }
      }
      IBLSamplerParameter.state = true;
    }
  }
}
export { EnviromentLight }